package com.example.gobang_system.service.impl;

import com.example.gobang_system.common.pojo.CommonResult;
import com.example.gobang_system.common.pojo.Room;
import com.example.gobang_system.common.pojo.UserInfo;
import com.example.gobang_system.common.util.JacksonUtil;
import com.example.gobang_system.dao.mapper.UserMapper;
import com.example.gobang_system.service.GameService;
import com.example.gobang_system.service.manager.OnlineUserManager;
import com.example.gobang_system.service.manager.RoomManager;
import com.example.gobang_system.websockethandler.param.PutChessParam;
import com.example.gobang_system.websockethandler.result.PutChessResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;

@Service
@Slf4j
public class GameServiceImpl implements GameService {
    @Autowired
    private RoomManager roomManager;
    @Autowired
    private OnlineUserManager onlineUserManager;
    @Autowired
    private UserMapper userMapper;


    /**
     * 处理落子请求
     * @param param
     * @param userInfo
     */
    @Override
    public void putChess(PutChessParam param, UserInfo userInfo) {
        try {
            // 获取游戏房间
            Room room = roomManager.getRoomByUserId(userInfo.getUserId());
            // 判断当前玩家是 玩家1 还是 玩家2
            int chess = userInfo.getUserId() == room.getUser1().getUserId()
                    ? 1 : 2;
            // 获取落子位置
            int row = param.getRow();
            int col = param.getCol();
            // 判断当前位置是否已经有子
            if (!room.isEmpty(row, col)) {
                log.info("已禁止 玩家 {} 在 {} 行 {} 列重复落子！",
                        userInfo.getUserName(), row, col);
                return;
            }
            // 落子
            room.putChess(row, col, chess);
            // 打印棋盘信息，方便观察落子情况
//            room.printBoard();
            // 进行胜负判断
            Long winner = room.checkWinner(row, col, chess);
            // 通知玩家
            WebSocketSession session1 = onlineUserManager.getFromRoom(room.getUser1().getUserId());
            WebSocketSession session2 = onlineUserManager.getFromRoom(room.getUser2().getUserId());
            if (null == session1 && null == session2) {
                // 玩家均掉线
                winner = -1L;
                log.info("游戏房间 {} 玩家1 和 玩家2 均掉线", room.getRoomId());
            } else if (null == session1) {
                winner = room.getUser2().getUserId();
                log.info("游戏房间 {} 玩家1 掉线", room.getRoomId());
            } else if (null == session2){
                winner = room.getUser1().getUserId();
                log.info("游戏房间 {} 玩家2 掉线", room.getRoomId());
            }
            // 构造响应并返回
            PutChessResult result = new PutChessResult(userInfo.getUserId(), row, col, winner);
            if (null != session1) {
                session1.sendMessage(new TextMessage(
                        JacksonUtil.writeValueAsString(CommonResult.success(result))));
            }
            if (null != session2) {
                session2.sendMessage(new TextMessage(
                        JacksonUtil.writeValueAsString(CommonResult.success(result))));
            }
            // 若胜负已分，则更新玩家分数，并销毁房间
            if (winner != 0) {
                if (winner == -1) {
                    log.info("房间 {} 游戏结束, 结果为平局");
                } else {
                    log.info("房间 {} 游戏结束, 获胜方id为 {}", room.getRoomId(), winner);
                    // 更新分数
                    Long loser = (room.getUser1().getUserId() == winner) ?
                            room.getUser2().getUserId() : room.getUser1().getUserId();
                    updateScore(winner , loser);
                }
                // 销毁游戏房间
                roomManager.remove(room.getRoomId(),
                        room.getUser1().getUserId(), room.getUser2().getUserId());
            }
        } catch (IOException e) {
            log.warn("发送落子响应异常 e: ", e);
        } catch (Exception e) {
            log.warn("落子异常 e: ", e);
        }
    }

    @Override
    public void updateScore(Long winner, Long loser) {
        userMapper.updateWinner(winner);
        userMapper.updateLoser(loser);
    }
}
